package com.stu.controller;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.stu.service.DemoService;
import com.stu.utils.DownFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@Api(tags = "测试")
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    DemoService demoService;
    @Autowired
    private ServletContext servletContext;

    public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐浏览器
            Base64.Encoder encoder = Base64.getEncoder();
            filename = "=?utf-8?B?" + encoder.encode(filename.getBytes("utf-8")) + "?=";
        } else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }

    @ApiOperation(value = "测试post请求", notes = "详细描述-测试post raw 提交数据")
    @PostMapping("/postmy")
    public String postJson(@RequestParam(defaultValue = "name-defaultValue", required = false) String name, @ApiParam(name = "data", value = "POST请求数据") @RequestBody String data, HttpServletRequest req) {
        System.out.println(name);
        System.out.println(StringUtils.repeat("-*", 8));
        System.out.println(data);
        System.out.println(req.getHeader("token"));
        return "ok";
    }

    @GetMapping("/url")
    public String getUrl(HttpServletRequest request) {
        System.out.println(request.getRequestURI());
        System.out.println(request.getRequestURL());
        StringBuffer url = request.getRequestURL();
        System.out.println("getContextPath" + request.getContextPath());
        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getSession().getServletContext().getContextPath()).append("/").toString();
        System.out.println(tempContextUrl);
        return tempContextUrl;

    }

    /**
     * ，默认值
     *
     * @param name
     * @return
     */
    @GetMapping("/hello")
    public String hello(@RequestParam(name = "name", defaultValue = "xxx") String name) {
        return "获取到的name是：" + name;
    }

    @ApiOperation(value = "不传递参数", notes = "不传递参数")
    @GetMapping("get")
    public LocalDateTime localDateTime(String success) {
        CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(5));
                System.out.println("DemoController.localDateTime");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(success);
        return demoService.localDateTime();
    }

    /**
     * RequestBody(表示 请求体 必须是JSON) RequestParam(url中的参数) get可以
     *
     * @return
     */
    @ApiOperation(value = "测试post请求 javaBean", notes = "详细描述-测试post raw 提交数据")
    @PostMapping("/postbean")
    public LocalDateTime postBean(@ApiParam(name = "data", value = "POST请求数据", required = true) @RequestBody ReqVo reqVo) {
        System.out.println(StringUtils.repeat("-*", 8));
        System.out.println(reqVo);
        return LocalDateTime.now();
    }

    @ApiOperation(value = "测试post请求", notes = "详细描述-测试post raw 提交数据")
    @RequestMapping("/post")
    public LocalDateTime get(@RequestParam(defaultValue = "name-defaultValue", required = false) String name, @ApiParam(name = "data", value = "POST请求数据") @RequestBody String data) {
        System.out.println(name);
        System.out.println(StringUtils.repeat("-*", 8));
        System.out.println(data);
        return LocalDateTime.now();
    }

    /**
     * 测试 long 全局配置
     */
    @ApiOperation(value = "测试ID", notes = "详细描述-测试ID精度丢失")
    @GetMapping("/id")
    public RespVo respVo() {
        ResoSon resoSon = new ResoSon(IdWorker.getId());
        List<ResoSon> list = new ArrayList<>();
        list.add(resoSon);
        RespVo respVo = new RespVo(IdWorker.getId(), LocalDateTime.now(), LocalDate.now(), new Date(), list);
        log.info("序列化{}", respVo);
        return respVo;
    }

    @ApiOperation(value = "测试response", notes = "详细描述-测试responseID精度丢失")
    @GetMapping("/response")
    public ResponseEntity<RespVo> response() {
        ResoSon resoSon = new ResoSon(IdWorker.getId());
        List<ResoSon> list = new ArrayList<>();
        list.add(resoSon);
        RespVo respVo = new RespVo(IdWorker.getId(), LocalDateTime.now(), LocalDate.now(), new Date(), list);
        log.info("序列化{}", respVo);
        // return ResponseEntity.ok(respVo);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    @GetMapping("downfile")
    public void downFile(HttpServletRequest req, HttpServletResponse response) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("pic/1.png");
        System.out.println(classPathResource.getFile().getPath());
        DownFile.downFile(req, response, classPathResource.getFile().toPath(), "1.png");
    }

    @GetMapping("downfile2")
    public void downFile2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("pic/1.png");
        System.out.println(classPathResource.getFile().getPath());
        // 2. 使用字节输入流加载文件进内存
        //2.1 需要获取绝对路径
        String realPath = classPathResource.getFile().getAbsolutePath();
        //2.2字节输入流关联
        FileInputStream file = new FileInputStream(realPath);

        //   3. 指定response的响应头： content-disposition:attachment;filename=xxx
        //3.1设置响应头类型
        String filename = "1.png";
        String mimeType = servletContext.getMimeType(filename);
        response.setHeader("content-type", mimeType);

            /*        * 中文文件问题
                    1. 获取客户端使用的浏览器版本信息
                    2. 根据不同的版本信息，设置filename的编码方式不同
            */
        String agent = request.getHeader("User-Agent");
        filename = getFileName(agent, filename);

        //3.2设置响应头打开方式 attachment (附件)形式打开
        response.setHeader("content-disposition", "attachment;filename=" + filename);
        // 4. 将数据写出到response输出流
        ServletOutputStream out = response.getOutputStream();
        //4.1字节缓冲输出
        byte[] buff = new byte[1024 * 8];
        int len = 0;
        while ((len = file.read(buff)) != -1) {
            out.write(buff, 0, len);
        }
        out.close();
    }

   
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class RespVo {

        private Long id;
        private LocalDateTime dats;
        private LocalDate localDate;
        private Date jdk7Date;
        private List<ResoSon> son;


        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
        }

    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class ResoSon {

        private Long ids;

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class ReqVo {

        private int id;
        private String name;
        private String hobby;

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
        }
    }

}
